﻿using OPCAutomation;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Chemistry.Models;
using System.Threading;
using System.Text.RegularExpressions;

namespace Chemistry.WorkFlow
{
    /// <summary>
    /// 苯酚异丁烯烷基化自控流程
    /// 分步考试
    /// </summary>
    public class Alkylation_Step : FlowBaseStep
    {
        #region 字段
        private static int _relay_command ;
        static double _phenol_value ;
        static double _pressure_value ;
        static double _temperature_value = 22;
        static double _flow_value = 10;

        static bool _isgetoverstate1 = false;
        static bool _isgetoverstate2 = false;
        static double _phenol_increment = 10;
        static double _phenol_decrement = 10;
        static double _temperature_increment = 2;
        static double _temperature_decrement = 1;
        static double _pressure_increment;
        static double _pressure_decrement;
        static double _flow_crement = 1;

        //命令
        private Tools.Tool.FlowCommand _flowcommand;
        string _switch1 = string.Empty;
        string _switch2 = string.Empty;
        string _prefix1 = string.Empty;
        string _prefix2 = string.Empty;
        string _llcmd = string.Empty;
        string _ywcmd = string.Empty;
        string _ylcmd = string.Empty;
        string _wdcmd = string.Empty;
        string _aicmd = string.Empty;
        string _relaycmd = string.Empty;
        int _warning1number = 0;
        int _warning2number = 0;
        int _fognumber = 0;
        int _stirnumber;

        //步骤标记
        int _replacecount = 1;
        bool _canopenempty = false;

         int open = 1; //0-48
         int close = 0; //1=49

        #endregion

        #region 组态开关状态
        /// <summary>
        /// 苯酚进料阀
        /// </summary>
        static bool ValveInPhenol_State = false;//苯酚进料阀
        /// <summary>
        /// 苯酚放料阀
        /// </summary>
        static bool ValveOutPhenol_State = false;//苯酚放料阀
        static bool ValveN2_State = false;
        static bool ValveEmpty_State = false;
        static bool ValveAutoEmpty_State = false;
        static bool ValveInCold_State = false;
        static bool ValveInHot_State = false;
        /// <summary>
        /// 异丁烯进料阀
        /// </summary>
        static bool ValveIsobutene_State = false;
        /// <summary>
        /// 紧急切断阀
        /// </summary>
        static bool ValveICutoff_State = false;
        /// <summary>
        /// 放料阀
        /// </summary>
        static bool ValveDischarge_State = false;
        /// <summary>
        /// 搅拌
        /// </summary>
        static bool ValveStir_State = false;
        /// <summary>
        /// 急停按钮状态
        /// </summary>
        static bool ValveStop_State = false;

        #endregion

        #region OPCItem

        //阀门
        OPCItem ValveInPhenol_item;
        OPCItem ValveOutPhenol_item;
        OPCItem ValveN2_item;
        OPCItem ValveEmpty_item;
        OPCItem ValveAutoEmpty_item;
        OPCItem ValveInCold_item;
        OPCItem ValveInHot_item;
        OPCItem ValveIsobutene_item;
        OPCItem ValveICutoff_item;
        OPCItem ValveDischarge_item;
        OPCItem ValveStir_item;
        OPCItem ValveStop_item;

        //管道
        OPCItem FlowEmpty_item;
        OPCItem FlowInCold_item;
        OPCItem FlowInHot_item;
        OPCItem FlowInPhenol_item;
        OPCItem FlowIsObutene_item;
        OPCItem FlowInN2_item;
        OPCItem FlowOutPhenol_item;
        OPCItem FlowOutSpices_item;

        //label
        OPCItem LabelLevel_item;
        OPCItem LabelOxygen_item;
        OPCItem LabelPressure_item;
        OPCItem LabelTemperature_item;
        OPCItem LabelFlow_item;


        //闪烁
        OPCItem FlashCatalyst_item;
        OPCItem FlashStir_item;
        OPCItem FlashPressure_item;
        OPCItem FlashTemperature_item;
        OPCItem FlashWarning_item;
        #endregion

        #region 初始化
        public Alkylation_Step(OPCServer opcserver, SerialPort port , bool isinner,List<ExaminationPoint> points)
        {
            _opcServer = opcserver;
            _serialPort = port;
            Isinner = isinner;
            base._points = points;
            InitFiled();
            InitOPC();
            InitOPCItem();
            InitSignal();
        }

        private void InitSignal()
        {
            if (Isinner)
            {
                ListenSignal();
                open = 1;
                close = 0;
            }
            else
            {
                InitFlowCommandData();
                _serialPort.DataReceived += _serialPort_DataReceived;
                InitOpcItemWithSerialPort();
                ListenSerialPort();
                open = 48;
                close = 49;
            }
        }

        private void InitFiled()
        {
            _relay_command = 0;
            _phenol_value = 500;//500----0
            _pressure_value = 0;
            _temperature_value = 22;
            _flow_value = 0;

            _isgetoverstate1 = false;
            _isgetoverstate2 = false;
            _phenol_increment = 10;
            _phenol_decrement =10;
            _temperature_increment = 2;
            _temperature_decrement = 1;
            _pressure_increment = 0.02;
            _pressure_decrement = 0.04;
            _flow_crement = 1;
        }

        private void InitFlowCommandData()
        {
            string classname = this.GetType().Name;
            classname = classname.Substring(0,classname.Length-5);
            _flowcommand = Tools.Tool.GetFlowCommand(classname);
            _switch1 = _flowcommand.Items.SingleOrDefault(i => i.Name == "switch1").Value;
            _switch2 = _flowcommand.Items.SingleOrDefault(i => i.Name == "switch2").Value;
            _prefix1 = _flowcommand.Items.SingleOrDefault(i => i.Name == "prefix1").Value;
            _prefix2 = _flowcommand.Items.SingleOrDefault(i => i.Name == "prefix2").Value;
            _llcmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "llcmd").Value;
            _ywcmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "ywcmd").Value;
            _ylcmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "ylcmd").Value;
            _wdcmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "wdcmd").Value;
            _aicmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "aicmd").Value;
            _relaycmd = _flowcommand.Items.SingleOrDefault(i => i.Name == "relaycmd").Value;
            _warning1number = int.Parse(_flowcommand.Items.SingleOrDefault(i => i.Name == "warning1").Value);
            _warning2number = int.Parse(_flowcommand.Items.SingleOrDefault(i => i.Name == "warning2").Value);
            _fognumber = int.Parse(_flowcommand.Items.SingleOrDefault(i => i.Name == "fog").Value);
            _stirnumber = int.Parse(_flowcommand.Items.SingleOrDefault(i => i.Name == "stir").Value);
        }

        private void InitOpcItemWithSerialPort()
        {
            SpFlowValue(_flow_value);                       
            SpTemperatureValue(_temperature_value);
            SpPressureValue(_pressure_value);
            SPWriteTool(_relay_command);
            SPYWValue(_phenol_value);
        }

        private void InitOPCItem()
        {
            //阀门
            ValveInPhenol_item = GetItem(FiledName.ValveInPhenol); ValveInPhenol_item.Close();
            ValveOutPhenol_item = GetItem(FiledName.ValveOutPhenol); ValveOutPhenol_item.Close();
            ValveN2_item = GetItem(FiledName.ValveN2); ValveN2_item.Close();
            ValveEmpty_item = GetItem(FiledName.ValveEmpty); ValveEmpty_item.Open();
            ValveAutoEmpty_item = GetItem(FiledName.ValveAutoEmpty); ValveAutoEmpty_item.Close();
            ValveInCold_item = GetItem(FiledName.ValveInCold); ValveInCold_item.Close();
            ValveInHot_item = GetItem(FiledName.ValveInHot); ValveInHot_item.Close();
            ValveIsobutene_item = GetItem(FiledName.ValveIsobutene); ValveIsobutene_item.Close();
            ValveICutoff_item = GetItem(FiledName.ValveICutoff); ValveICutoff_item.Open();
            ValveDischarge_item = GetItem(FiledName.ValveDischarge); ValveDischarge_item.Close();
            ValveStir_item = GetItem(FiledName.ValveStir); ValveStir_item.Close();
            ValveStop_item = GetItem(FiledName.ValveStop); ValveStop_item.Close();

            //管道
            FlowEmpty_item = GetItem(FiledName.FlowEmpty); FlowEmpty_item.Close();
            FlowInCold_item = GetItem(FiledName.FlowInCold); FlowInCold_item.Close();
            FlowInHot_item = GetItem(FiledName.FlowInHot); FlowInHot_item.Close();
            FlowInPhenol_item = GetItem(FiledName.FlowInPhenol); FlowInPhenol_item.Close();
            FlowIsObutene_item = GetItem(FiledName.FlowIsObutene); FlowIsObutene_item.Close();
            FlowInN2_item = GetItem(FiledName.FlowN2); FlowInN2_item.Close();
            FlowOutPhenol_item = GetItem(FiledName.FlowOutPhenol); FlowOutPhenol_item.Close();
            FlowOutSpices_item = GetItem(FiledName.FlowOutSpices); FlowOutSpices_item.Close();

            //label
            LabelLevel_item = GetItem(FiledName.LabelLevel); LabelLevel_item.Write(_phenol_value);
            LabelOxygen_item = GetItem(FiledName.LabelOxygen); LabelOxygen_item.Write(22);
            LabelPressure_item = GetItem(FiledName.LabelPressure); LabelPressure_item.Write(_pressure_value);
            LabelTemperature_item = GetItem(FiledName.LabelTemperature); LabelTemperature_item.Write(_temperature_value);
            LabelFlow_item = GetItem(FiledName.LabelFlow); LabelFlow_item.Write(0);

            //闪烁
            FlashCatalyst_item = GetItem(FiledName.FlashCatalyst); FlashCatalyst_item.Close();
            FlashStir_item = GetItem(FiledName.FlashStir); FlashStir_item.Close();
            FlashPressure_item = GetItem(FiledName.FlashPressure); FlashPressure_item.Close();
            FlashTemperature_item = GetItem(FiledName.FlashTemperature); FlashTemperature_item.Close();
            FlashWarning_item = GetItem(FiledName.FlashWarning);
            FlashWarning_item.Write(0);
        }
        private void ListenSignal()
        {
            Task t = new Task(() =>
            {
                while (!_listenCts.IsCancellationRequested)
                {
                    ValveInPhenol_State = Convert.ToInt32(ReadItem(FiledName.ValveInPhenol)) == open;
                    ValveOutPhenol_State = Convert.ToInt32(ReadItem(FiledName.ValveOutPhenol)) == open;
                    ValveN2_State = Convert.ToInt32(ReadItem(FiledName.ValveN2)) == open;
                    ValveEmpty_State = Convert.ToInt32(ReadItem(FiledName.ValveEmpty)) == open;
                    ValveAutoEmpty_State = Convert.ToInt32(ReadItem(FiledName.ValveAutoEmpty)) == open;
                    ValveInCold_State = Convert.ToInt32(ReadItem(FiledName.ValveInCold)) == open;
                    ValveInHot_State = Convert.ToInt32(ReadItem(FiledName.ValveInHot)) == open;
                    ValveIsobutene_State = Convert.ToInt32(ReadItem(FiledName.ValveIsobutene)) == open;
                    ValveICutoff_State = Convert.ToInt32(ReadItem(FiledName.ValveICutoff)) == open;
                    ValveDischarge_State = Convert.ToInt32(ReadItem(FiledName.ValveDischarge)) == open;
                    ValveStir_State = Convert.ToInt32(ReadItem(FiledName.ValveStir)) == open;
                    ValveStop_State = Convert.ToInt32(ReadItem(FiledName.ValveStop)) == open;

                    DateTime dtnow = DateTime.Now;
                    Step step = new Step()
                    {
                        Status =
                        {
                         { StatusName.液位, _phenol_value},
                         { StatusName.压力, _pressure_value},
                         { StatusName.温度, _temperature_value},
                         { StatusName.苯酚进料阀,Convert.ToInt32(ReadItem(FiledName.ValveInPhenol)) },
                         { StatusName.苯酚放料阀,Convert.ToInt32(ReadItem(FiledName.ValveOutPhenol)) },                         
                        { StatusName.自动放空阀,Convert.ToInt32(ReadItem(FiledName.ValveAutoEmpty))},
                        { StatusName.冷水阀,Convert.ToInt32(ReadItem(FiledName.ValveInCold))},
                        { StatusName.蒸汽阀,Convert.ToInt32(ReadItem(FiledName.ValveInHot))},
                        { StatusName.异丁烯阀,Convert.ToInt32(ReadItem(FiledName.ValveIsobutene))},
                        { StatusName.紧急切断阀,Convert.ToInt32(ReadItem(FiledName.ValveICutoff))},
                        { StatusName.放料阀,Convert.ToInt32(ReadItem(FiledName.ValveDischarge))},

                        { StatusName.氮气阀,-1},
                        { StatusName.放空阀,-1},
                        { StatusName.氮气阀2,-1},
                        { StatusName.放空阀2,-1},

                        { StatusName.搅拌阀,Convert.ToInt32(ReadItem(FiledName.ValveStir))},
                         { StatusName.急停按钮,Convert.ToInt32(ReadItem(FiledName.ValveStop))},
                        },
                        Date = dtnow,

                    };
                    if (_replacecount == 1)
                    {
                        step.Status[StatusName.氮气阀] = Convert.ToInt32(ReadItem(FiledName.ValveN2));
                        if (_canopenempty)
                        {
                            if (_pressure_value == 0)
                            {
                                step.Status[StatusName.放空阀] = Convert.ToInt32(ReadItem(FiledName.ValveEmpty));
                                LabelOxygen_item.Write(5);
                                _replacecount = 2;
                                _canopenempty = false;
                            }
                        }
                    }
                    _isListenSingnalover = true;
                    _steps.Add(step);
                    Thread.Sleep(_sleepfast);
                }
            });
            t.Start();
        }

        #endregion

        #region 监听步骤，计分
        int ValveInPhenol = -1, ValveOutPhenol = -1, ValveAutoEmpty = -1, ValveInCold = -1,
                        ValveEmpty = -1, ValveN2 = -1, ValveInHot = 1, ValveIsobutene = -1,
                        ValveICutoff = -1, ValveDischarge = -1, ValveStir = -1, ValveStop = -1;

        private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int n = _serialPort.BytesToRead;
            byte[] data = new byte[n];
            _serialPort.Read(data, 0, data.Length);

            string temp = Encoding.Default.GetString(data);
            //Console.WriteLine("recv:\t"+_recv);
            if (temp.Contains("\n"))
            {
                Match match = Regex.Match(temp, @"\d{5}_\d{3}");
                if (match.Success)
                {
                    string s = match.Groups[0].Value.Split('_')[1];
                    int v = Convert.ToInt32(s);
                    string r = Convert.ToString(v, 2).PadLeft(8,'0');
                    string first = match.Groups[0].Value.Split('_')[0];

                    if (first == _prefix1)
                    {
                        #region 21651
                        ValveAutoEmpty = Convert.ToInt32(r[0]);
                        ValveInPhenol = Convert.ToInt32(r[1]);
                        ValveStop = Convert.ToInt32(r[2]);
                        ValveStir = Convert.ToInt32(r[3]);
                        ValveOutPhenol = Convert.ToInt32(r[4]);
                        ValveEmpty = Convert.ToInt32(r[5]);
                        ValveInCold = Convert.ToInt32(r[6]);
                        ValveIsobutene = Convert.ToInt32(r[7]);

                        ValveInPhenol_State = ValveInPhenol == open;
                        ValveStop_State = ValveStop == open;
                        ValveStir_State = ValveStir == open;
                        ValveOutPhenol_State = ValveOutPhenol == open;
                        ValveEmpty_State = ValveEmpty == open;
                        ValveInCold_State = ValveInCold == open;
                        ValveIsobutene_State = ValveIsobutene == open;
                        ValveAutoEmpty_State = ValveAutoEmpty == open;


                        _isgetoverstate1 = true;
                        #endregion
                    }
                    else if (first == _prefix2)
                    {

                        ValveInHot = Convert.ToInt32(r[0]);
                        ValveN2 = Convert.ToInt32(r[1]);
                        ValveDischarge = Convert.ToInt32(r[2]);
                        ValveICutoff = Convert.ToInt32(r[3]);

                        ValveInHot_State = ValveInHot == open;
                        ValveN2_State = ValveN2 == open;
                        ValveDischarge_State = ValveDischarge == open;
                        ValveICutoff_State = ValveICutoff == open;
                        _isgetoverstate2 = true;
                    }
                    DateTime dtnow = DateTime.Now;
                    Step step = new Step()
                    {
                        Status =
                        {
                         { StatusName.液位, _phenol_value},
                         { StatusName.压力, _pressure_value},
                         { StatusName.温度, _temperature_value},
                         { StatusName.苯酚进料阀,ValveInPhenol },
                         { StatusName.苯酚放料阀,ValveOutPhenol },                         
                        { StatusName.自动放空阀,ValveAutoEmpty},
                        { StatusName.冷水阀,ValveInCold},
                        { StatusName.蒸汽阀,ValveInHot},
                        { StatusName.异丁烯阀,ValveIsobutene},
                        { StatusName.紧急切断阀,ValveICutoff},
                        { StatusName.放料阀,ValveDischarge},

                        { StatusName.氮气阀,-1},
                        { StatusName.放空阀,-1},
                        { StatusName.氮气阀2,-1},
                        { StatusName.放空阀2,-1},

                        { StatusName.搅拌阀,ValveStir},
                         { StatusName.急停按钮,ValveStop},
                        },
                        Date = dtnow,

                    };
                    FillStep(ValveEmpty, ValveN2, step);
                    _steps.Add(step);

                }
            }
        }

        private void FillStep(int valveEmpty, int valveN2, Step step)
        {
            if (_replacecount == 1)
            {
                step.Status[StatusName.氮气阀] = valveN2;
                if (_canopenempty)
                {
                    if (_pressure_value == 0 && valveEmpty == open)
                    {
                        step.Status[StatusName.放空阀] = valveEmpty;
                        LabelOxygen_item.Write(5);
                        _replacecount = 2;
                        _canopenempty = false;
                    }
                }
            }
           
        }


        private void ListenOPCRelation()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
            {
                #region 苯酚物进料
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveInPhenol_State)
                        {
                            if (!Isinner) ValveInPhenol_item.Open();
                            FlowInPhenol_item.StartFlow();
                            _phenol_value += _phenol_increment;
                            if (_phenol_value <= 600)
                            {
                                LabelLevel_item.Write(_phenol_value);
                                SPYWValue(_phenol_value);
                            }
                            else if (_phenol_value > 650)
                            {
                                BeginWarning(WarningType.苯酚物液位过高);
                            }
                        }
                        else
                        {
                            if (!Isinner) ValveInPhenol_item.Close();
                            StopWarning(WarningType.苯酚物液位过高);
                            FlowInPhenol_item.StopFlow();
                            if (_phenol_value > 650)
                            {
                                _phenol_value = 600;
                                LabelLevel_item.Write(_phenol_value);
                                SPYWValue(_phenol_value);
                            }
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });
                #endregion

                #region 苯酚物放料
                Task.Run(
                    () =>
                    {
                        while (!_listenCts.IsCancellationRequested)
                        {
                            if (ValveOutPhenol_State)
                            {
                                if (!Isinner) ValveOutPhenol_item.Open();
                                FlowOutPhenol_item.StartFlow();
                                _phenol_value -= _phenol_decrement;

                                if (_phenol_value < 30)
                                    _phenol_decrement = 5;
                                else
                                    _phenol_decrement = 10;

                                if (_phenol_value >= 0)
                                {
                                    LabelLevel_item.Write(_phenol_value);
                                    SPYWValue(_phenol_value);
                                }
                                else
                                {
                                    _phenol_value = 0;
                                    FlowOutPhenol_item.StopFlow();
                                }
                            }
                            else
                            {
                                if (!Isinner) ValveOutPhenol_item.Close();
                                FlowOutPhenol_item.StopFlow();
                            }
                            Thread.Sleep(_sleepfast);
                        }
                    }
                    );
                #endregion

                #region 充氮气
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveN2_State)
                        {
                            _pressure_increment = 0.02;
                            if (!Isinner) ValveN2_item.Open();
                            FlowInN2_item.StartFlow();
                            _pressure_value += _pressure_increment;
                            _pressure_value = Math.Round(_pressure_value, 2);
                            LabelPressure_item.Write(_pressure_value);                            
                            SpPressureValue(_pressure_value);
                            if (_pressure_value > 0.3)
                            {
                                FlashPressure_item.StartFlow();
                                BeginWarning(WarningType.氮气置换压力过高);
                            }

                            if (_pressure_value > 0.2)
                                _canopenempty = true;
                        }
                        else
                        {
                            if (!Isinner) ValveN2_item.Close();
                            if (_pressure_value < 0.3)
                                StopWarning(WarningType.氮气置换压力过高);
                            FlowInN2_item.StopFlow();
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });
                #endregion

                #region 放空
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveEmpty_State)
                        {
                            if (!Isinner) ValveEmpty_item.Open();
                            FlowEmpty_item.StartFlow();

                            _pressure_value = Math.Round(_pressure_value, 2);
                            _pressure_value -= _pressure_decrement;

                            _pressure_decrement = _pressure_value < 0.05 ? 0.01 : 0.04;

                            if (_pressure_value >= 0.01)
                            {
                                LabelPressure_item.Write(_pressure_value);                                
                                SpPressureValue(_pressure_value);
                            }
                            else
                            {
                                _pressure_value = 0;
                                LabelPressure_item.Write(_pressure_value);
                                FlashPressure_item.Close();

                            }
                        }
                        else
                        {
                            if (!Isinner) ValveEmpty_item.Close();
                            FlowEmpty_item.StopFlow();
                            FlashPressure_item.Close();
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });
                #endregion

                int sleeplong = 800;
                #region 冷却水阀
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveInCold_State)
                        {
                            if (!Isinner) ValveInCold_item.Open();
                            FlowInCold_item.StartFlow();
                            _temperature_value = Math.Round(_temperature_value, 2);
                            _temperature_value -= _temperature_decrement;

                            if (_temperature_value < 20)
                            {
                                _temperature_decrement = 0;
                            }
                            else if (_temperature_value < 200)
                            {
                                _temperature_decrement = 2;
                                FlashTemperature_item.StopFlow();
                            }
                                
                            LabelTemperature_item.Write(_temperature_value);
                            SpTemperatureValue(_temperature_value);
                        }
                        else
                        {
                            if (!Isinner) ValveInCold_item.Close();
                            FlowInCold_item.StopFlow();
                        }
                        Thread.Sleep(sleeplong);
                    }
                });
                #endregion

                #region 蒸汽阀
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveInHot_State)
                        {
                            if (!Isinner) ValveInHot_item.Open();
                            FlowInHot_item.StartFlow();

                            //控制反应温度
                            if (_temperature_value >= 90)//100
                                _temperature_increment = 0.1;
                            else if (_temperature_value > 85)
                                _temperature_increment = 0.2;
                            else if (_temperature_value > 80)
                                _temperature_increment = 1;
                            else
                                _temperature_increment = 2;

                           // if (_temperature_value <= 90)//100
                            {
                                _temperature_value = Math.Round(_temperature_value, 2);
                                _temperature_value += _temperature_increment;
                                LabelTemperature_item.Write(_temperature_value);
                                SpTemperatureValue(_temperature_value);
                            }
                        }
                        else
                        {
                            if (!Isinner) ValveInHot_item.Close();
                            FlowInHot_item.StopFlow();
                        }
                        Thread.Sleep(sleeplong);
                    }
                });
                #endregion

                #region 异丁烯阀 +
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveIsobutene_State)
                        {
                            if (!Isinner) ValveIsobutene_item.Open();
                            _flow_value = Math.Round(_flow_value, 2);
                            LabelFlow_item.Write(_flow_value);
                            FlowIsObutene_item.StartFlow();

                            //控制反应压力
                            //if (_pressure_value < 0.6)
                            {
                                _pressure_increment = 0.03;
                                _flow_crement = 1;
                            }
                            if (_pressure_value > 0.6 && _pressure_value < 0.8)
                            {
                                _pressure_increment = 0.02;
                                _flow_crement = 0.5;
                            }

                           // if (_pressure_value <= 0.8)
                            {
                                _pressure_value += _pressure_increment;
                                _pressure_value = Math.Round(_pressure_value, 2);
                                SpPressureValue(_pressure_value);
                                LabelPressure_item.Write(_pressure_value);

                                _flow_value += _flow_crement;
                                SpFlowValue(_flow_value);
                            }
                            
                        }
                        else
                        {
                            if (!Isinner) ValveIsobutene_item.Close();
                            LabelFlow_item.Write(0);
                            FlowIsObutene_item.StopFlow();
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });
                #endregion

                #region 放料阀
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (ValveDischarge_State)
                        {
                            if (!Isinner) ValveDischarge_item.Open();
                            FlowOutSpices_item.StartFlow();
                        }
                        else
                        {
                            if (!Isinner) ValveDischarge_item.Close();
                            FlowOutSpices_item.StopFlow();
                        }
                        Thread.Sleep(_sleepfast);
                    }
                });
                #endregion

                #region 搅拌釜状态
                Task.Run(() =>
                {
                    while (!_listenCts.IsCancellationRequested)
                    {
                        if (!ValveStir_State)
                        {
                            StopStir();
                            if (!Isinner)
                            {
                                ValveStir_item.Close();
                            }

                        }
                        else
                        {
                            if (!Isinner) ValveStir_item.Open();
                            FlashStir_item.Open();
                            Thread.Sleep(300);
                            FlashStir_item.Close();
                            Thread.Sleep(300);
                            BeginStir();

                        }
                        Thread.Sleep(_sleepfast);
                    }
                });
                #endregion
            }));
        }

        void CalcFlowAndStep()
        {
            #region 计算流程 
            //进料
            var phenol_in_item = _steps.Where(i => i.Status[StatusName.苯酚进料阀] == open)
                .OrderByDescending(i => i.Status[StatusName.液位]).ThenByDescending(i => i.Date).FirstOrDefault();

            //出料
            var phenol_out_item = _steps.Where(i => i.Status[StatusName.苯酚放料阀] == open)
               .OrderBy(i => i.Status[StatusName.液位])
               .ThenByDescending(i => i.Date).FirstOrDefault();

            //氮气1
            var n2_pressure_item1 = _steps.Where(i => i.Status[StatusName.氮气阀] == open)
                .OrderByDescending(i => i.Status[StatusName.压力]).ThenByDescending(i => i.Date).FirstOrDefault();

            //放空1
            var o2_pressure_item1 = n2_pressure_item1 != null ? _steps.Where(i => i.Status[StatusName.放空阀] == open && i.Date > n2_pressure_item1.Date)
                .OrderBy(i => i.Status[StatusName.压力]).ThenByDescending(i => i.Date).FirstOrDefault() : null;

         
            //升温
            var hot_temperature_item = _steps.Where(i => i.Status[StatusName.蒸汽阀] == open)
                .OrderByDescending(i => i.Status[StatusName.温度]).ThenByDescending(i => i.Date).FirstOrDefault();

            //异丁烯升压
            var isobutene_item = _steps.Where(i => i.Status[StatusName.异丁烯阀] == open && i.Status[ StatusName.紧急切断阀]==open)
                .OrderByDescending(i => i.Status[StatusName.压力]).ThenByDescending(i => i.Date).FirstOrDefault();
           
            //冷水降温
            var cold_item = _steps.Where(i => i.Status[StatusName.冷水阀] == open)
                .OrderBy(i => i.Status[StatusName.温度]).ThenByDescending(i => i.Date).FirstOrDefault();
            
            //最后一步出料阀
            var discharge_open_item = _steps.Where(i => i.Status[StatusName.放料阀] == open).OrderByDescending(i => i.Date).FirstOrDefault();

            //反应时一直开着  
            var stir_open_first = _steps.FirstOrDefault(i => i.Status[StatusName.搅拌阀] == open);//首次打开的时间

            #endregion

            #region 添加step
            _dicSteps.Clear();
            //进料 
            InsertRangeValueStep("苯酚进料", ValueName.液位 , phenol_in_item, StatusName.苯酚放料阀);

            #region 出料
            var phenol_out_step = base._points.SingleOrDefault(i => i.Description == "苯酚出料");
            if (phenol_out_step.IsChecked)
            {
                if (phenol_out_item != null)
                {
                    double phenol_in_level = phenol_in_item == null ? 450 : phenol_in_item.Status[StatusName.液位];
                    var diff = phenol_in_level - phenol_out_item.Status[StatusName.液位];
                    if (diff >= phenol_out_step.Value1)
                    {
                        string tempformart = string.Format(
                            "{0}:液位差{1}{2}{3}",
                            phenol_out_step.Description,
                            diff,
                            phenol_out_step.Operator,
                            phenol_out_step.Value1);
                        _dicSteps.Add("苯酚出料", new StepDescription() { Description = tempformart, IsRight = true });
                    }
                    else
                    {
                        string tempformart = string.Format(
                            "{0}:液位差{1}{2}{3}",
                            phenol_out_step.Description,
                            diff,
                            "低于",
                            phenol_out_step.Value1);
                        _dicSteps.Add("苯酚出料", new StepDescription() { Description = tempformart, IsRight = true });
                    }
                }
                else
                {
                    _dicSteps.Add("苯酚出料", new StepDescription() { Description = phenol_out_step.Description + "：无操作", IsRight = false });
                }
            } 
            #endregion
            
            #region 氮气置换
            var n2_replace_step = base._points.SingleOrDefault(i => i.Description == "氮气置换");
            if (n2_replace_step.IsChecked)
            {
                if (n2_pressure_item1 != null)
                {
                    var pressure_value = n2_pressure_item1.Status[StatusName.压力];
                    if (pressure_value > 0.3)
                    {
                        string temp = string.Format("反应釜压力:{0}MPa,高于0.3Mpa,压力过高", pressure_value);
                        _dicSteps.Add("氮气置换-充氮气", new StepDescription() { Description = temp, IsRight = false });
                    }
                    else if (pressure_value >= 0.2 && pressure_value <= 0.3)
                    {
                        string temp = string.Format("反应釜压力:{0}MPa,在0.2Mpa-0.3Mpa范围内", pressure_value);
                        _dicSteps.Add("氮气置换-充氮气", new StepDescription() { Description = temp, IsRight = true });
                    }
                    else
                    {
                        string temp = string.Format("反应釜压力:{0}MPa,低于0.2Mpa,压力不足", pressure_value);
                        _dicSteps.Add("氮气置换-充氮气", new StepDescription() { Description = temp, IsRight = false });
                    }
                }
                else
                {
                    _dicSteps.Add("氮气置换-充氮气", new StepDescription() { Description = "氮气置换-充氮气，无操作", IsRight = false });
                }

                if (o2_pressure_item1 != null)
                {
                    var pressure_value = o2_pressure_item1.Status[StatusName.压力];
                    if (pressure_value <= 0.01)
                    {
                        string temp = string.Format("打开放空阀，降压至{0}MPa", pressure_value);
                        _dicSteps.Add("氮气置换-放空", new StepDescription() { Description = temp, IsRight = true });
                    }
                    else
                    {
                        string temp = string.Format("打开放空阀，反应釜压力{0}MPa，未降到0.01MPa以下", pressure_value);
                        _dicSteps.Add("氮气置换-放空", new StepDescription() { Description = temp, IsRight = false });
                    }
                }
                else
                {
                    _dicSteps.Add("氮气置换-放空", new StepDescription() { Description = "氮气置换-放空，无操作", IsRight = false });
                }
            }
            #endregion

            //打开蒸汽阀80-100
            InsertRangeValueStep("通入蒸汽", ValueName.温度, hot_temperature_item, StatusName.温度);

            //通入异丁烯
            InsertRangeValueStep("通入异丁烯", ValueName.压力, isobutene_item, StatusName.压力);
            
            //冷水降温
            InsertRangeValueStep("通入冷水", ValueName.温度, cold_item, StatusName.温度);

            // 开搅拌 / 放料
            InsertActionStep("打开搅拌", stir_open_first);
            InsertActionStep("放料", discharge_open_item);


            //异常处理
            #region 压力异常
            var pressure_abnormal_point = base._points.SingleOrDefault(i => i.Description == "压力突变异常");
            if (pressure_abnormal_point.IsChecked)
            {
                var openair_item = _steps.Where(i => i.Status[StatusName.压力] <= 0.01 && i.Date > _pressureAbnormalData)
                    .OrderByDescending(i => i.Date).FirstOrDefault();
                var closeh2_item = _steps.Where(i => i.Status[StatusName.异丁烯阀] == close && i.Date > _pressureAbnormalData)
                    .OrderByDescending(i => i.Date).FirstOrDefault();
                if (openair_item != null && closeh2_item != null)
                {
                    _dicSteps.Add("处理压力突变异常", new StepDescription() { Description = pressure_abnormal_point.Description + "：完成", IsRight = true });
                }
                else
                {
                    _dicSteps.Add("处理压力突变异常", new StepDescription() { Description = pressure_abnormal_point.Description + "：未完成", IsRight = false });
                }
            }
            #endregion

            #region 温度异常
            var temperature_abnormal_point = base._points.SingleOrDefault(i => i.Description == "温度突变异常");
            if (temperature_abnormal_point.IsChecked)
            {
                var openair_item = _steps.Where(i => i.Status[StatusName.温度] <= 50 && i.Date > _temperatureAbnormalDate)
                    .OrderByDescending(i => i.Date).FirstOrDefault();
                var closehot_item = _steps.Where(i => i.Status[StatusName.蒸汽阀] == close && i.Date > _temperatureAbnormalDate)
                    .OrderByDescending(i => i.Date).FirstOrDefault();
                if (openair_item != null && closehot_item != null)
                {
                    _dicSteps.Add("处理温度突变异常", new StepDescription() { Description = temperature_abnormal_point.Description + "：完成", IsRight = true });
                }
                else
                {
                    _dicSteps.Add("处理温度突变异常", new StepDescription() { Description = temperature_abnormal_point.Description + "：未完成", IsRight = false });
                }
            }
            #endregion

            #region 泄漏异常
            var leak_abnormal_point = base._points.SingleOrDefault(i => i.Description == "泄漏异常");
            if (leak_abnormal_point.IsChecked)
            {
                var closeHot_item = _steps.Where(i => i.Status[StatusName.蒸汽阀] == close && i.Date > _leakAbnormalDate)
                    .OrderByDescending(i => i.Date).FirstOrDefault();
                var closeH2_item = _steps.Where(i => i.Status[StatusName.异丁烯阀] == close && i.Date > _leakAbnormalDate)
                    .OrderByDescending(i => i.Date).FirstOrDefault();
                var stop_item = _steps.Where(i => i.Status[StatusName.急停按钮] == open && i.Date > _leakAbnormalDate)
                    .OrderByDescending(i => i.Date).FirstOrDefault();
                if (closeHot_item != null && closeH2_item != null && stop_item != null)
                {
                    _dicSteps.Add("处理泄漏异常", new StepDescription() { Description = leak_abnormal_point.Description + "：完成", IsRight = true });
                }
                else
                {
                    _dicSteps.Add("处理泄漏异常", new StepDescription() { Description = leak_abnormal_point.Description + "：未完成", IsRight = false });
                }
            }
            #endregion


            #endregion
        }

        private void ListenSerialPort()
        {
            string chkcmd_1 = _flowcommand.Items.SingleOrDefault(i => i.Name == "chkcmd1").Value; // "#RYW21651&";
            string chkcmd_2 = _flowcommand.Items.SingleOrDefault(i => i.Name == "chkcmd2").Value; //"#RYW21652&";

            Task listSerialPortState = new Task(
                () =>
                {
                    try
                    {
                        if (_serialPort.IsOpen)
                        {
                            lock (this)
                            {
                                Thread.Sleep(100);
                                _serialPort.Write(chkcmd_1);
                            }
                        }
                    }
                    catch (Exception)
                    {
                    }



                    try
                    {
                        if (_serialPort.IsOpen)
                        {
                            lock (this)
                            {
                                Thread.Sleep(100);
                                _serialPort.Write(chkcmd_2);
                            }

                        }
                    }
                    catch (Exception)
                    {
                    }
                });
            listSerialPortState.Start();
        }

        #endregion

        #region 处理异常的方法
     

        #region 温度异常

        protected override void BeginTempretureAbnormal(double value)
        {
            _warningDicionary.Add(WarningType.温度异常, false);
            Task.Run(() =>
            {
                while (_temperature_value < value)
                {
                    _temperature_value += 5;
                    LabelTemperature_item.Write(_temperature_value);
                    SpTemperatureValue(_temperature_value);
                    Thread.Sleep(_sleepfast);
                }
                _temperatureAbnormalDate = DateTime.Now;
                BeginWarning(WarningType.温度异常);
                FlashTemperature_item.StartFlow();
                HandleTempretureAbnormal();
            });
        }
        private void HandleTempretureAbnormal()
        {
            Parallel.Invoke(CloseHotValve4TpAbnormal, OpenColdValve4TpAbnormal);

            StopWarning(WarningType.温度异常);
            _warningDicionary[WarningType.温度异常] = true;
        }

        private void OpenColdValve4TpAbnormal()
        {
            while (!_listenCts.IsCancellationRequested)//true
            {
                if (_temperature_value > 50)
                {
                    Thread.Sleep(_sleepfast);
                }
                else
                {
                    break;
                }
            }
        }

        void CloseHotValve4TpAbnormal()
        {
            while (!_listenCts.IsCancellationRequested)//true
            {
                if (!ValveInHot_State)
                {
                    break;
                }
                Thread.Sleep(_sleepfast);
            }
        }


        #endregion

        #region 压力异常
        private void HandlePressureAbnormal()
        {
            Parallel.Invoke(() =>
            {
                OpenAirValve4PAbnormal();
            }, () =>
            {
                //关闭氢气紧急切断阀
                CloseH2Valve4PAbnormal();
            });

            StopWarning(WarningType.压力异常);
            _warningDicionary[WarningType.压力异常] = true;
        }

        private void CloseH2Valve4PAbnormal()
        {
            while (!_listenCts.IsCancellationRequested)
            {
                if (!ValveICutoff_State)
                    break;
                Thread.Sleep(_sleepfast);
            }
        }

        private void OpenAirValve4PAbnormal()
        {
            _pressure_decrement = 0.06;//加快降压
            double const_pg = _pressure_value;
            //打开放空阀
            while (!_listenCts.IsCancellationRequested)//true
            {
                if (ValveEmpty_State)
                {
                    if (_pressure_value <= 0)
                    {
                        break;
                    }
                }
                else
                {
                    if (_pressure_value >= 0 && _pressure_value < const_pg)
                    {
                        SendMessage("反应釜压力未降至0，请打开放空阀");
                    }
                }
                Thread.Sleep(_sleepfast);
            }
        }

        protected override void BeginPressureAbnormal(double value)
        {        
            _warningDicionary.Add(WarningType.压力异常, false);
            Task.Run(() =>
            {
                while (_pressure_value < value)
                {
                    _pressure_value += 0.1;
                    LabelPressure_item.Write(_pressure_value);
                    SpPressureValue(_pressure_value);
                    Thread.Sleep(_sleepfast);
                }
                _pressureAbnormalData = DateTime.Now;
                BeginWarning(WarningType.压力异常);
                FlashPressure_item.StartFlow();
                HandlePressureAbnormal();
            });
        }
       
        #endregion

        #region 泄漏

        protected override void BeginLeakAbnormal()
        {
            _isleakAbnormal = false;
            BeginWarning(WarningType.泄漏);
            BeginLeak();
            _leakAbnormalDate = DateTime.Now;
            _warningDicionary.Add(WarningType.泄漏, false);
            HandleLeakAbnormal();
        }

        private void HandleLeakAbnormal()
        {
            //打开急停按钮
            while (!_listenCts.IsCancellationRequested)//true
            {
                if (ValveStop_State)
                {
                    AddCompose("处理泄漏异常：按下急停按钮");
                    break;
                }
                Thread.Sleep(_sleepfast);
            }
            //关闭蒸汽和异丁烯
            Parallel.Invoke(() =>
            {

                while (!_listenCts.IsCancellationRequested)//true
                {
                    if (!ValveInHot_State)
                    {
                        AddCompose("处理泄漏异常：关闭蒸汽阀");
                        break;
                    }
                    Thread.Sleep(_sleepfast);
                }
            }, () =>
            {
                while (!_listenCts.IsCancellationRequested)//true
                {
                    if (!ValveIsobutene_State)
                    {
                        AddCompose("处理泄漏异常：关闭异丁烯进料阀");
                        break;
                    }
                    Thread.Sleep(_sleepfast);
                }
            });

            StopWarning(WarningType.泄漏);
            _warningDicionary[WarningType.泄漏] = true;
        }

        #endregion
        #endregion

        #region 重写公共方法
        public override void Begin()
        {
            ListenOPCRelation();//联动
            CheckAbnormalPoint();
        }
        bool _isListenSingnalover = false;
        public override async Task<string> CheckDefault()
        {
            StringBuilder builder = new StringBuilder();
            await Task.Run(() =>
            {
                if (!Isinner)
                {
                    while (!_isgetoverstate1 || !_isgetoverstate2)
                    {
                        Thread.Sleep(_sleepfast);
                    }
                }
                else
                {
                    while (!_isListenSingnalover)
                    {
                        Thread.Sleep(_sleepfast);
                    }
                }
                if (ValveInPhenol_State)
                    builder.AppendLine("苯酚进料阀未关闭");
                if (ValveOutPhenol_State)
                    builder.AppendLine("苯酚放料阀未关闭");
                if (ValveN2_State)
                    builder.AppendLine("氮气阀未关闭");
                if (!ValveEmpty_State)
                    builder.AppendLine("手动放空阀未打开");
                if (ValveAutoEmpty_State)
                    builder.AppendLine("自动放空阀未关闭");
                if (ValveInCold_State)
                    builder.AppendLine("冷水阀未关闭");
                if (ValveInHot_State)
                    builder.AppendLine("蒸汽阀未关闭");
                if (ValveIsobutene_State)
                    builder.AppendLine("异丁烯进料阀未关闭");
                if (ValveDischarge_State)
                    builder.AppendLine("放料阀未关闭");
                if (!ValveICutoff_State)
                    builder.AppendLine("紧急切断阀未打开");
                if (ValveStir_State)
                    builder.AppendLine("搅拌按钮未关闭");
                if (ValveStop_State)
                    builder.AppendLine("急停按钮未关闭");
                if(ValveDischarge_State)
                    builder.AppendLine("出料阀未关闭");
            });
            return builder.ToString();
        }

        public override void Over()
        {
            Close();
            CalcFlowAndStep();
            Score = CalcScore();
            CloseAllRelay();
            Finish();
        }

        public override void Close()
        {
            this._listenCts.Cancel();
            base.Close();
            if (_serialPort != null)
            {
                _serialPort.DataReceived -= _serialPort_DataReceived;
                _serialPort.Close();
            }
        }
        #endregion


        #region 写串口数据
        void SpFlowValue(double value)
        {
            WriteFlowValue(_llcmd, 1, value);
            WriteAIvalue(_aicmd, 2, value);
        }

        void SpPressureValue(double value)
        {
            WritePressureValue(_ylcmd, value);
            WriteAIvalue(_aicmd, 1, value);
        }

        void SpTemperatureValue(double value)
        {
            WriteTemperatureValue(_wdcmd, value);
            WriteAIvalue(_aicmd, 3, value);
        }

        private void SPYWValue(double value)
        {
            if (Isinner) return;
            double write_value = 255*value/600;
            write_value = Math.Round(write_value, 0);
            string cmdvalue = write_value.ToString().PadLeft(3, '0');
            string cmd = string.Format(_ywcmd, cmdvalue);
            if (_serialPort.IsOpen)
            {
                lock (this)
                {
                    Thread.Sleep(120);
                    _serialPort.Write(cmd);
                }
            }
        }

        #endregion

        #region 操作继电器
        /// <summary>
        /// 写继电器
        /// </summary>
        /// <param name="number">0-128， </param>
        void SPWriteTool(int number)
        {
            if (Isinner) return;
            WriteTool(_relaycmd, number);
        }
        /// <summary>
        /// 关闭所有继电器
        /// </summary>
        void CloseAllRelay()
        {
            SPWriteTool(0);
        }

        /// <summary>
        /// 开始预警
        /// </summary>
        /// <param name="type">预警类型</param>
        void BeginWarning(WarningType type)
        {
            if (!_warningtypes.Contains(type))
            {
                FlashWarning_item.Open();
                _warningtypes.Add(type);
                _relay_command = _relay_command | _warning1number;//响
                _relay_command = _relay_command | _warning2number;//亮
                SPWriteTool(_relay_command);
            }
        }

        void StopWarning(WarningType type)
        {
            if (_warningtypes.Contains(type))
            {
                FlashWarning_item.Close();
                _relay_command = (~_warning1number) & _relay_command;
                _relay_command = (~_warning2number) & _relay_command;
                SPWriteTool(_relay_command);
                _warningtypes.Remove(type);
            }
        }

        /// <summary>
        /// 开始泄漏
        /// </summary>
        void BeginLeak()
        {
            FlashWarning_item.Open();
            _relay_command = _relay_command | _fognumber;
            SPWriteTool(_relay_command);
            Thread.Sleep(500);
            StopLeak();

        }
        /// <summary>
        /// 停止泄漏
        /// </summary>
        void StopLeak()
        {
            FlashWarning_item.Close();
            _relay_command = _relay_command & (~_fognumber);
            SPWriteTool(_relay_command);
        }

        void BeginStir()
        {
            _relay_command = _relay_command | _stirnumber;
            SPWriteTool(_relay_command);
        }

        void StopStir()
        {
            _relay_command = _relay_command & (~_stirnumber);
            SPWriteTool(_relay_command);
        }
        #endregion

        #region 枚举
        enum FiledName
        {
            //开关
            ValveInPhenol, ValveOutPhenol, ValveN2, ValveEmpty, ValveAutoEmpty, ValveInCold, ValveInHot, ValveIsobutene, ValveICutoff, ValveDischarge, ValveStir,
            //管道
            FlowEmpty, FlowInCold, FlowInHot, FlowInPhenol, FlowIsObutene, FlowN2, FlowOutPhenol, FlowOutSpices, ValveStop,
            //label
            LabelLevel, LabelOxygen, LabelPressure, LabelTemperature, LabelFlow,
            //闪烁
            FlashCatalyst, FlashStir, FlashPressure, FlashTemperature,
            FlashWarning
        }

        enum WarningType
        {
            氮气置换压力过高,
            温度异常,
            压力异常,
            泄漏,
            反应釜压力过高,
            反应釜内丙烯含量过高,
            苯酚物液位过高,
            通入苯酚物过量,
        }

        enum StatusName
        {
            液位, 压力, 温度, 苯酚进料阀, 苯酚放料阀, 放空阀, 氮气阀, 自动放空阀, 冷水阀, 蒸汽阀, 异丁烯阀, 紧急切断阀, 放料阀, 搅拌阀, 放空阀2, 氮气阀2,
            急停按钮
        }
        #endregion

    }
}
